home *** CD-ROM | disk | FTP | other *** search
/ PCMania 64 / PCMania CD64_1.iso / phy / phy003 / files / articulo.007 < prev    next >
Encoding:
Text File  |  1997-04-12  |  8.2 KB  |  253 lines

  1. *cX             Curso de programación
  2.            orientada a objetos (III)
  3.  
  4. *cR     Teoria y uso de los streams
  5. *c^
  6.   Otra de esas nuevas cositas "filosóficas"
  7. que nos proporciona la POO es el envio de
  8. mensajes a los objetos (de esto ya hemos
  9. hablado), y la pantalla, como el disco u
  10. otros sistemas de comunicación, son objetos
  11. y como tales se define una nueva forma de
  12. interactuación. Frente a los betustos y a
  13. veces frustrantes *cAprintf()*c^ y *cAfread()*c^
  14. se define ahora *cAcin*c^ i *cAcout*c^ (dentro de
  15. la libreria *cAiostream.h*c^) que aceptan cual-
  16. quier tipo de datos predefinidos y cual-
  17. quiera que le podamos definir en un futuro
  18. (esto es una cosa fantástica que veremos
  19. más adelante).
  20.  
  21.   Antes, con *cAprintf*c^, por ejemplo, teniamos
  22. que decir de que tipo de datos se trataba lo
  23. que queriamos escribir:
  24.  
  25. *cH     printf("Mi casa es de color %s", color);
  26. *c^
  27. Ahora eso ya no hace falta, simplemente
  28. llamamos para escribir lo que haya
  29. que escribir que ya se las arreglará el com-
  30. pilador para saber de que tipo son los datos.
  31. La sintaxis de C++ para escribir en streams
  32. (que así se llaman en inglés los ficheros,
  33. entre los que se encuentra la pantalla (aquí
  34. todo son ficheros, como en UNIX!! :) se po-
  35. dria ejemplificar así:
  36. *cH    cout << "Mi casa es de color " << color;
  37. *c^
  38.   Por supuesto, se pueden meter más signos
  39. *cA<<*c^ para seguir escribiendo más cosas e
  40. incluso para hacer retornos de carros y todo
  41. lo que se podia hacer con el C tradicional.
  42. Al igual que el objeto *cAcout*c^ redirige a la
  43. salida estandar, el antes mencionado *cAcin*c^
  44. hace lo própio con la entrada estandar.
  45. Además en otro número veremos como todo esto
  46. es tambien aplicable a los ficheros de
  47. nuestro disco duro haciendonos la vida más
  48. facil.
  49. *cR
  50.      Métodos inline
  51. *c^
  52.   Los métodos inline son el sustituto natural
  53. de las macros de C. Han de definirse e imple-
  54. mentarse obligatoriamente detro de la própia
  55. definición de la clase y no pueden ser está-
  56. ticos (ya veremos que es ésto). Un ejemplo
  57. podria ser el siguiente:
  58. *cH
  59.  class Inlines {
  60.    private:
  61.      int status;
  62.      [...]
  63.    public:
  64.      [...]
  65.     inline int error(void) { return status; }
  66.      [...]
  67.   };
  68. *c^
  69.   Observa que la definición y el cuerpo del
  70. método van unidos y no hay que redefinirlo
  71. en ningún otro sítio. Esta función de ejemplo,
  72. lo único que hace es devolver un valor de una
  73. variable privada que supuestamente controla
  74. los errores de la clase; por ello podria re-
  75. sultar un poco lento implementarlo como un
  76. método normal (porque habria que añadir una
  77. llamada a procedimiento y demás).
  78. *cR
  79.      Constructores y destructores
  80. *c^
  81.   Muchas veces, si programas en Pascal usando
  82. TPUs, habrás usado la parte de la TPU que se
  83. ejecuta siempre que se incluye ésta, para
  84. inicializar variables o mostrar mensajes,
  85. pero tambien otras veces te hubiera podido
  86. hacer falta hacer lo mismo para acabar y no
  87. lo has podido hacer. Los constructores de
  88. C++ son unos métodos que se ejecutan cada vez
  89. que creas una instancia de un objeto y que te
  90. permiten inicializar variables, pedir
  91. memoria, etc. Los destructores son un método
  92. que tiene cada clase y que se ejecuta al eli-
  93. minarse cada objeto instanciado.
  94.   Para ver la potencia de los constructores y
  95. destructores podemos imaginar que queremos
  96. crear una clase que maneje una lista de núme-
  97. ros complejos u otros objetos de forma diná-
  98. mica (pidiendo memoria cada vez que se añade
  99. un elemento y liberandola cada vez que se
  100. elimina uno). Si usaramos los métodos
  101. tradicionales, tendriamos que pedir memoria
  102. explícitamente en cada método, usando el pa-
  103. radigma de la OO podemos crear un constructor
  104. que cada vez que se instancie un objeto, re-
  105. serve la memoria suficiente para contenerse y
  106. luego automáticamente se libere esa memoria.
  107.   La definición de los constructores es bas-
  108. tante sencilla: se trata de un método que no
  109. devuelve nada y que tiene el mismo nombre que
  110. la clase que lo contiene. De forma similar,
  111. el destructor es un método que no devuelve
  112. nada y tampoco recibe parámetros de entrada
  113. y cuyo nombre es el mismo de la clase,
  114. pero precedido del signo tilde *cA~*c^ (ALT+126).
  115. Un ejemplo:
  116. *cH
  117.  class Coche {
  118.      [...]
  119.    public:
  120.      [...]
  121.        Coche(char **Marca, char **Modelo);
  122.       ~Coche();
  123.   };
  124.  
  125.  Coche :: Coche(char **Marca, char **Modelo) {
  126.    [...]
  127.    }
  128.  
  129.  Coche :: ~Coche() {
  130.    [...]
  131.    }
  132. *c^
  133.   Podemos observar que la definición debe
  134. estar en la parte pública ya que si no fuese
  135. así, el compilador no podria acceder a los
  136. métodos *cACoche*c^ y *cA~Coche*c^. Hay que observar tam-
  137. bien, que el destructor NUNCA puede llevar
  138. parámetros, mientras el constructor puede
  139. llevarlos o no.
  140. *cR
  141.      La herencia
  142. *c^
  143.   Como parábola de la realidad, la heréncia
  144. es una forma de que los que vienen después
  145. cojan lo que se ha creado por/para los que
  146. habia antes. Imaginemos que tenemos una
  147. clase "Avion" en la que están definidas una
  148. série de abstracciones generales de todos los
  149. aviones (combustible, altura máxima, peso,
  150. etc). Ahora queremos hacer una clase
  151. "Bombardero" y nos encontramos con el pro-
  152. blema de que tenemos que reescribir todos los
  153. métodos anteriores junto con las variables y
  154. demás. ¿Como solucionar ésto? Con la herencia.
  155. Si de alguna manera pudiesemos aprovechar el
  156. trabajo realizado con "Avion" y no tenerlo
  157. que reescribir para "Bombardero" estariamos
  158. ganando mucho tiempo y trabajo. Si hacemos
  159. que la clase "Bombardero" HEREDE de "Avion",
  160. solucionamos el problema; podriamos hacerlo
  161. así:
  162. *cH
  163.  class Avion {
  164.    private:
  165.      int combustible;
  166.      int velocidad;
  167.    public:
  168.      void acelera(int v);
  169.           Avion();
  170.          ~Avion();
  171.   };
  172.  
  173.  class Bombardero : public Avion {
  174.    private:
  175.      int num_bombas;
  176.    public:
  177.      inline int lanza(void)
  178.               { return --num_bombas; }
  179.           Bombardero();
  180.          ~Bombardero();
  181.   };
  182. *c^
  183.   La primera clase ("Avion") no tiene nada
  184. nuevo, pero la clase "Bombardero" ya va te-
  185. niendo en la primera línea cosas "extrañas".
  186. Con ese tipo de definición, lo que queremos
  187. decirle al compilador es: "defineme una
  188. clase llamada Bombardero que herede pública-
  189. mente (lo que era publico que lo siga siendo)
  190. de la clase Avion todos sus atributos". Así,
  191. en la clase "Bombardero", no tendremos
  192. como privada sólo 1 variable ("num_bombas"),
  193. sino que tendremos 3, las 2 de "Avion" y la
  194. própia. De la misma forma, no tendremos como
  195. pública sólo el método "lanza()" y el
  196. constructor+destructor, sino que heredamos el
  197. método "acelera()" de la clase padre.
  198. *cR
  199.     Uso de directivas del compilador
  200. *c^
  201.   No sólo para la POO es necesario usar bien
  202. las directivas que te ofrece el compilador,
  203. es una forma de hacer más robusto y legible
  204. nuestro código. Las que se usan principal-
  205. mente suelen ser *cA#ifdef*c^, *cA#ifndef*c^, *cA#endif*c^ e
  206. *cA#include*c^. No hay mucho que decir acerca de
  207. todas ellas, pues su uso está claro, pero es
  208. muy interesante que comienzes a meterlas por
  209. tus clases para que el compilador no te de
  210. grandes errores. Un uso frequente y que
  211. recomiendo es el siguiente:
  212. *cH
  213.   // Fichero "claseA.hpp"
  214.  
  215.   #ifndef __CLASE_A__
  216.   #define __CLASE_A__
  217.  
  218.   class A {
  219.     [...]
  220.    };
  221.  
  222.   #endif
  223. *cR
  224.    Reglas prácticas para compilar
  225. *c^
  226.   Si estas muy habituado a usar C sin crearte
  227. ficheros de proyecto, puede que caigas muchas
  228. veces (hasta que te acostumbres) en el error
  229. de incluir tanto la definición como la imple-
  230. mentación de cada una de las clases usadas.
  231. Si lo haces así e incluyes una misma clase
  232. en 2 lugares distintos, el compilador te dará
  233. un error de duplicación en la definición.
  234.   Para evitar todos los errores de este tipo,
  235. lo mejor es tener claro donde debes poner las
  236. directivas del compilador y usar los ficheros
  237. de proyecto. Para usarlos sólo tienes que
  238. crear uno con el entorno que te proporciona
  239. el compilador e insertar allí todos los
  240. ficheros auxiliares que uses. Además, sólo
  241. deberás incluir los ficheros de definición de
  242. cada clase usada y nunca la implementación de
  243. éstas.
  244.   Ya hay suficiente por éste número, en el
  245. próximo intentaremos ver nuestros primeros
  246. programas compilables, pero hasta entonces
  247. es muy recomendable que vayas investigando
  248. por tu cuenta (hay muchas clases interesantes
  249. en los compiladores comerciales).
  250. Hasta la vista.
  251.  
  252.                         *cG     Navi Dj.
  253.